package infiews.crawler;

import infiews.crawler.exceptions.CrawlerDatabaseException;
import infiews.util.Database;
import infiews.util.Logger;
import infiews.web.Page;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

public class TaskManager {	

    public TaskManager(){}
	
	public void setThreads( List<WebCrawler> threads){
		this.threads = threads;
	}
	
	public List<WebCrawler> getThreads(){
		return this.threads;
	}

	public void addBad( Page page ){
		if(page != null)
			badList.put(page.getURL(),page);
	}
	
	public void addTasks(List<Page> pages) {
		for( int i=0; i<pages.size();i++ ){
			if( !taskList.contains(pages.get(i)) && !resultList.containsValue(pages.get(i)) ){
				taskList.add( pages.get(i) );
			}
		}
	}
	
	public void addTask(Page page) {
		taskList.add( page );
	}
	
	public void addTask(String url){
		taskList.add( new Page(url) );
	}

	public int fillTaskList(int max, List<Page> result) {
		log.info("FIll task list executed.");
		int i=0;
		while(!taskList.isEmpty() && i < max){
			result.add(taskList.poll());
			i++;
		}
		return i;
	}
	
	public void addPage( Page page ){
		Iterator<Page> walker = taskList.iterator();
		while( walker.hasNext() ){
			Page tPage = walker.next();
			if( resultList.containsValue(tPage) ){
				walker.remove();
			}
		}
		resultList.put( page.getURL(), page );
	}
	
	public Boolean hasPage( String url ){
		if(url != null)
			return resultList.containsKey(url) || badList.containsKey(url);
		else return false;
	}

	public Boolean hasTask( Page page ){
		if( taskList.contains(page)){
			return true;
		}else{
			for( int i=0; i<threads.size(); i++ ){
				try{
					if( threads.get(i)!=null && threads.get(i).getTaskList().contains(page)){
						return true;
					}
				}catch( Exception e ){
					log.exception(e);
				}
			}
			return false;
		}
	}

	public void addToResultList(List<Page> pages){
		for(Page page : pages){
			this.resultList.put(page.getURL(), page);
		}
	}
	
	public Page getPage( String url ){
		if( resultList.containsKey(url) ){
			return resultList.get(url);
		}else{
			return new Page( url );
		}
	}
	
	public long getTaskCount() {
		return taskList.size();
	}
	
	public boolean isFinished() {
		return isFinished;
	}
	
	public void finish() {
		isFinished = true;
	}
	
	public void flushPages() throws CrawlerDatabaseException {
		Database db = Crawler.getDb();
		Set<String> keyList = resultList.keySet();
		Iterator<String> walker = keyList.iterator();
		while( walker.hasNext() ){
			String key = walker.next();

			if(resultList.get(key).isMustSave())
				db.savePage(resultList.get(key));
		}
		resultList = null;
		badList = null;
	}

    private LinkedBlockingQueue<Page> taskList = new LinkedBlockingQueue<Page>();
    private ConcurrentHashMap<String,Page> resultList = new ConcurrentHashMap<String,Page>();
    private ConcurrentHashMap<String,Page> badList = new ConcurrentHashMap<String,Page>();

    private List<WebCrawler> threads = new ArrayList<WebCrawler>();

    private static TaskManager instance;
    private Logger log = Crawler.log();
    private boolean isFinished = false;
}